import ThemeBtn from '@/components/antd-comp/theme-btn'
import { WorkflowRunningStatus } from '@/components/workflow/types'
import { useWorkFlowStore } from '@/store/workflowStore'
import cn from '@/util/classnames'
import { RiCloseLine } from '@remixicon/react'
import { Form, Input, InputNumber, Switch, Upload, Progress, message } from 'antd'
import { Rule } from 'antd/es/form'
import JSON5 from 'json5'
import { uniqueId } from 'lodash'
import { memo, useEffect, useRef, useState } from 'react'
import { getWorkFlowDetailApi } from '../API'
import { graphToRunGraph, inputToRunInput } from '../compatible'
import { useAutoSave } from '../hooks/use-save'
import { findStartVariables, getFirstItem, getUserInputsInfo } from '../utils'
import './style.less'
import { InboxOutlined } from '@ant-design/icons'
import { Tabs } from 'antd'
import InputFormCont from './components/input-form'
import ResultPanel from './components/result'

export const FLOW_URL = '/api/v1/workflow/run'



const RunPanel = ({ node, changeBottomPanelStatus, closePanel = (status: boolean) => {} }: any) => {
  const panelWidth = 500
  const {
    flow,
    flowVariables,
    running,
    setRunning,
    updateSingleRunningInfo,
    clearRunInfo,
    setErrorInfo,
    updateRunningToError,
    setRunTime,
    setDisabledPublish,
    setDisabledEdit
  } = useWorkFlowStore()
  const { getMergedGraph, autoSave } = useAutoSave()

  const [form] = Form.useForm()
  const startVariables = findStartVariables(flowVariables)
  // console.log('RunPanel: flow, flowVariables, startVariables', flow, flowVariables, startVariables)

  const [localRunning, setLocalRunning] = useState(false)
  const [activeKey, setActiveKey] = useState('input')

  useEffect(() => {
    setDisabledEdit(localRunning)
  }, [localRunning])

  const userInput = useRef(null)

  const uniqueInputId = useRef('')

  useEffect(() => {
    uniqueInputId.current = uniqueId('flow_')
    setResults(null) // 清空结果
    return () => {
      uniqueInputId.current = ''
    }
  }, [flow.id])

  /**
   * 处理用户输入
   */
  function handleUserInput(data: any) {
    const inputs = getUserInputsInfo(userInput.current?.data)
    updateSingleRunningInfo(data.message.node_id, WorkflowRunningStatus.Running, { inputs })
  }

  const errInfo = useRef(null)

  const endNodeInfo = useRef(null)
  /**
   * 处理接口响应
   */
  // 添加结果状态
  const [results, setResults] = useState<any>(null)
  
  // 修改 handleNodeRun 函数，在合适的位置添加结果更新
  function handleNodeRun(data: any, errorMessages:string[]) {
    const nodeId = data.message?.node_id
    if (data.message?.reason) {
      const err = `节点${data.message.name}运行失败：${data.message.reason}`
      errInfo.current = err
      updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Failed)
      errorMessages.push(err)
      setErrorInfo( errorMessages.join('[@split@]'))
      changeBottomPanelStatus(true)
      return
    }
    if (data.type === 'start') {
      const inputs = getUserInputsInfo(userInput.current?.data)
      updateSingleRunningInfo(data.message.node_id, WorkflowRunningStatus.Running, {
        inputs,
        startTime: new Date().valueOf()
      })
    } else if (data.type === 'end') {
      if (!nodeId.startsWith('end_')) {
        updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, { endTime: new Date().valueOf() })
        
      }
      if (nodeId.startsWith('llm_')) {
        updateLlmNode(nodeId, data.message.log_data)
      } else if (nodeId.startsWith('code_')) {
        updateCodeNode(nodeId, data.message.log_data)
      } else if (nodeId.startsWith('tool_')) {
        updateToolNode(nodeId, data.message.log_data)
      } else if (nodeId.startsWith('intend_')) {
        updateIntendNode(nodeId, data.message.log_data)
      } else if (nodeId.startsWith('if-else_')) {
        updateElseIfNode(nodeId, data.message.log_data)
      } else if (nodeId.startsWith('qa_retriever')) {
        updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, {
          inputs: data?.message?.log_data?.input,
          outputs: data?.message?.log_data?.output?.output
        })
      } else if (nodeId.startsWith('end_')) {
        endNodeInfo.current = {
          id: nodeId,
          data: data.message.log_data
        }
      } else if (nodeId.startsWith('http_request_')) {
        updateHttpNode(nodeId, data.message.log_data)
      } else if (nodeId.startsWith('iteration_')) {
        updateIterationNode(nodeId, data.message.log_data)
      } else if (nodeId.startsWith('doc_extractor_')) {
        updateDocExtractorNode(nodeId, data.message.log_data)
      }  else if (nodeId.startsWith('list_')) {
        updateListNode(nodeId, data.message.log_data)
      } else if (nodeId.startsWith('text_concatenation_')) {
        updateTextConcatenationNode(nodeId, data.message.log_data)
      } 
    }
  }

  function updateLlmNode(nodeId: string, logData: any) {
    updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, {
      inputs: getFirstItem(logData?.user_prompt),
      system_prompt: getFirstItem(logData?.system_prompt),
      outputs: logData?.output?.output
    })
  }

  function updateHttpNode(nodeId: string, logData: any) {
    updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, {
      //inputs: logData?.request,
      outputs: JSON.stringify(logData?.response, null, 2),
    })
  }

  function updateIterationNode(nodeId: string, logData: any) {
    updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, {
      //inputs: inputs && inputs.length > 0 ? inputs : null,
      outputs: JSON.stringify(logData.output?.output || logData?.output, null, 2)
    })
  }

  function updateDocExtractorNode(nodeId: string, logData: any) {
    const outputs = logData.output?.output || logData?.output
    updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, {
      outputs: outputs ? JSON.stringify(outputs , null, 2) : ""
    })
  }

  function updateListNode(nodeId: string, logData: any) {
    const outputs = logData.output?.output?.output || logData?.output
    updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, {
      outputs: outputs ? JSON.stringify(outputs , null, 2) : ""
    })
  }

  function updateTextConcatenationNode(nodeId: string, logData: any) {
    const outputs = logData.output?.output?.output || logData?.output
    updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, {
      outputs: logData?.output?.output
    })
  }

  function updateCodeNode(nodeId: string, logData: any) {
    updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, {
      inputs: JSON.stringify(logData.code_input, null, 2),
      outputs: JSON.stringify(logData.code_output, null, 2)
    })
  }

  function updateEndNode(nodeId: string, logData: any) {
    const outputs = logData.output_msg
    updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, { outputs })
  }

  const updateRunTimer = id => {
    getWorkFlowDetailApi(id).then((res: any) => {
      if (res?.flow?.run_timestamp) {
        setRunTime(res.flow.run_timestamp.replace('T', ' '))
      }
    })
  }
  function updateToolNode(nodeId: string, logData: any) {
    const obj = logData.input
    const inputs = []
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        inputs.push({ variable: key, value: obj[key] })
      }
    }
    updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, {
      inputs: inputs && inputs.length > 0 ? inputs : null,
      outputs: logData.output?.output || logData?.output
    })
  }
  function updateIntendNode(nodeId: string, logData: any) {
    // 输入
    const inputs = Object.entries(logData.input).map(([variable, value]) => ({ variable, value }))
    // 输出
    const list =
      logData.id !== undefined && logData.reason !== undefined
        ? {
            id: logData.id,
            reason: logData.reason
          }
        : []
    const outputsList = Object.entries(list).map(([variable, value]) => ({ variable, value }))
    updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, {
      inputs: inputs.length > 0 ? inputs : null,
      outputsList: outputsList.length > 0 ? outputsList : null
    })
  }

  function updateElseIfNode(nodeId: string, logData: any) {
    const obj = logData
    const inputs = []
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        inputs.push({ variable: key, value: obj[key] })
      }
    }
    updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, {
      inputs: inputs && inputs.length > 0 ? inputs : null
      // outputs: logData.output?.output
    })
  }

  /**
   * 处理接口异常信息
   * error未包含异常节点的id，暂时先简单处理：
   * 1、error发生时将所有running中的节点设置为运行失败，
   * 2、并主动关闭连接
   * 3、失败原因不单独显示，直接显示一个统一的失败面板
   */
  function handleNodeError(data: any) {
    console.log('handleNodeError: data', data)
    if (!errInfo.current) {
      setErrorInfo(data.message)
      updateRunningToError()
      changeBottomPanelStatus(true)
    }
    setLocalRunning(false)
    setDisabledPublishFalseDelay()
  }

  const handleFlowRun = async (runData, uid) => {
    const errorMessages = [];
    try {
      const response = await fetch(`${FLOW_URL}/${flow.id}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Accept: 'text/event-stream'
        },
        body: JSON.stringify(runData)
      })

      // 检查HTTP状态码
      if (!response.ok) {
        throw new Error(`请求失败，状态码: ${response.status}`)
      }

      const reader = response.body.getReader()
      const decoder = new TextDecoder('utf-8')
      const processLine = (line: string) => {
        // console.info('processLine line:', line)
        if (line.startsWith('data: {')) {
          try {
            const data = JSON5.parse(line.slice(6))

            // if (data.category === 'user_input') {
            //   handleUserInput(data)
            // } else
            if (data.category === 'node_run' && data.message?.node_id) {
              handleNodeRun(data,errorMessages)
            } else if (data.category === 'error') {
              handleNodeError(data)
            } else if (data.type === 'close') {
              updateRunTimer(flow.id)
              setLocalRunning(false)
              setDisabledPublishFalseDelay()
            }
          } catch (error) {
            console.error('解析数据异常', error, line)
            handleNodeError({
              message: `返回数据异常：${line}`
            })
          }
        } else if (line === 'data: [DONE]') {
          console.info('工作流运行返回结束', endNodeInfo.current)
          if (endNodeInfo.current) {
            // 结束节点只收集数据不运行，为方便展示开始和结束实际设置为1，显示0.00s
            updateSingleRunningInfo(endNodeInfo.current.id, WorkflowRunningStatus.Succeeded, {
              startTime: 1,
              endTime: 1
            })
            updateEndNode(endNodeInfo.current.id, endNodeInfo.current.data)
            setResults(endNodeInfo.current.data)
          }
          return true
        } else {
          if (line) {
            if (line.startsWith(': ping')) {
              console.log(`等待服务器响应：${line}`)
            } else {
              const errMsg = line.startsWith('data: ') ? line.slice(6) : line
              handleNodeError({
                message: errMsg
              })
            }
          }
        }
      }

      let buffer = ''
      while (true) {
        const { done, value } = await reader.read()
        if (done) break

        if (uid !== uniqueInputId.current) {
          break
        }

        const chunk = decoder.decode(value, { stream: true })
        buffer += chunk
        const lines = buffer.split('\r\n')
        buffer = lines.pop() || ''

        for (const line of lines) {
          if (processLine(line)) {
            break
          }
        }
      }
      console.log('数据处理结束')
      updateRunTimer(flow.id)
      setLocalRunning(false)
      setDisabledPublishFalseDelay()
    } catch (error) {
      console.error('请求过程中出现问题:', error)
      handleNodeError({
        message: `发生了助理解决不了的问题，工程师正在努力恢复，请稍等。`
      })
    } finally {
      setLocalRunning(false)
      setDisabledPublishFalseDelay()
    }
  }
  /* 处理undefined转化null */
  function convertUndefinedToNull(obj) {
    if (typeof obj !== 'object' || obj === null) {
      return obj
    }
    for (const key in obj) {
      if (obj[key] === undefined) {
        obj[key] = null
      } else if (typeof obj[key] === 'object') {
        // 如果属性值是对象，则递归调用此函数
        obj[key] = convertUndefinedToNull(obj[key])
      }
    }
    return obj
  }

  const initWsAndRun = async values => {
    const initGraph = graphToRunGraph(flow, getMergedGraph(flow.id))
    const runInput = inputToRunInput(startVariables.id, values, startVariables.variables)
    userInput.current = runInput
    const status = await autoSave(flow.id, true) // 试运行前进行保存，防止出现用户编辑后里面运行
    if (status) {
      handleFlowRun(
        {
          init_data: initGraph.data,
          input_data: {
            // [startVariables.id]: runInput.data[startVariables.id].data
            [startVariables.id]: convertUndefinedToNull(runInput.data[startVariables.id].data)
          }
        },
        uniqueInputId.current
      )
    } else {
      setRunning(false)
      setLocalRunning(false)
      setDisabledPublishFalseDelay()
    }
    console.log('graphToRunGraph result', initGraph)
    console.log('inputToRunInput result', runInput)
  }
  /* run运行 */
  const handleRunEvent = () => {
    clearRunInfo()
    endNodeInfo.current = null
    setResults(null)
    changeBottomPanelStatus(false)
    form
      .validateFields()
      .then(async values => {
        setActiveKey('result')  // 切换到结果标签页
        console.log('handleRunEvent values', values)
        setRunning(true)
        setLocalRunning(true)
        setDisabledPublish(true)
        initWsAndRun(values)
      })
      .catch(err => {
        console.error('err', err)
      })
  }
  const getInitialValues = (startVariables: any) => {
    if (!startVariables || !startVariables.variables) {
      return {}
    }

    return startVariables.variables.reduce((acc: any, item: any) => {
      if (item.type === 'boolean') {
        acc[item.variable] = true // 设置布尔类型的默认值为 true
      }
      return acc
    }, {})
  }

  // 运行成功后限制用户1.5s后才能点发布，让用户缓缓
  const setDisabledPublishFalseDelay = () => {
    setTimeout(() => {
      setDisabledPublish(false)
    }, 1500)
  }

  // 处理文件上传
  // const handleUpload = async (options: any) => {
  //   const { file, onSuccess, onError, onProgress } = options
  //   const formData = new FormData()
    
  //   formData.append('files', file)
  //   try {
  //     const response = await fetch('/api/v1/common/upload/batch', {
  //       method: 'POST',
  //       body: formData
  //     })

  //     if (response.ok) {
  //       const result = await response.json()
  //       onProgress({ percent: 100 }, file)
  //       onSuccess(result, file)
  //       return result.data[0]
  //     }
  //     throw new Error('上传失败')
  //   } catch (error) {
  //     message.error('文件上传失败')
  //     onError(error)
  //   }
  // }
  
  const CustomTabLabel = ({ label }) => {
    return (
      <div style={{ fontWeight: 'bold' }}>{label}</div>
    );
  };
  
  return (
    <div
      className={cn(
        'custom-run-container',
        'fixed right-[0] top-[57px] h-[calc(100vh-57px)] bg-[#ffffff]',
        'overflow-visible  shadow-lg transition-all'
      )}
      style={{
        width: `${panelWidth}px`
      }}
    >
      <div
        className={cn('h-[100%] overflow-y-auto rounded-2xl transition-all', 'border-[1px] border-transparent')}
        style={{
          width: `${panelWidth}px`
        }}
      >
        <div className="sticky top-0 z-10 cursor-move border-b-[0.5px] border-black/5">
          <div className="flex h-[56px] items-center bg-[#ffffff] pb-1 pt-1">
            <div className="leading-0 flex w-[320px] px-2 py-[5px]">试运行</div>
            <div
              className="flex shrink-0 items-center justify-end text-gray-500"
              style={{
                width: '148px'
              }}
            >
              <div className="mx-3 h-3.5 w-[1px] bg-[#eaecf0]" />
              <div className="flex h-6 w-6 cursor-pointer items-center justify-center rounded-md hover:bg-black/5">
                <RiCloseLine
                  className="text-text-tertiary h-4 w-4"
                  onClick={() => {
                    closePanel()
                  }}
                />
              </div>
            </div>
          </div>
        </div>
      
       {/* 替换原来的 InputFormCont 为 Tabs 结构 */}
       <Tabs className='px-2'
          activeKey={activeKey} 
          onChange={setActiveKey}
          items={[
            {
              key: 'input',
              label: <CustomTabLabel label="输入" />,
              children: (
                <InputFormCont 
                  form={form}
                  startVariables={startVariables}
                  running={running}
                  localRunning={localRunning}
                  handleRunEvent={handleRunEvent}
                />
              )
            },
            {
              key: 'result',
              label: <CustomTabLabel label="结果" />,
              disabled: !running && !localRunning && !results,  // 添加这行，只有运行中或有结果时才能切换
              children: (
                <ResultPanel 
                  running={running && localRunning}
                  results={results}
                />
              )
            }
          ]}
        />
      </div>
    </div>
  )
}

export default memo(RunPanel)
